import os
from typing import TextIO


class Config:
    def __init__(self) -> None:
        self.key = None
        self.value = None
        self.children = []

    def addValue(self, value) -> None:
        if self.value is None:
            self.value = value
        else:
            self.value += ",%s" % value


class ConvertProperties2Yaml:
    PROPERTIES_SUFFIX = ".properties"
    YAML_SUFFIX = ".yaml"
    TAB = "    "
    ONE_SPACE = " "
    ARRAY_VALUE_START_MARK = "  - "

    def __init__(self, path: str) -> None:
        if path is None or len(path) <= 0 or not path.endswith(self.PROPERTIES_SUFFIX):
            raise RuntimeError("the argument's format is not matech")
        self.oldPath = path
        lastIndex = len(path) - len(self.PROPERTIES_SUFFIX)
        self.newPath = path[0:lastIndex] + self.YAML_SUFFIX
        self.configMap = {}
        if not os.path.isfile(path) or os.path.isfile(self.newPath):
            raise RuntimeError("properties file not found in %s, or yaml file has exists in %s" % (
                self.oldPath, self.newPath))

    def convert(self) -> None:
        with open(self.oldPath, mode='r') as file:
            lines = file.readlines()
            for line in lines:
                self.analyze(line)
        self.write()

    def write(self) -> None:
        values = list(self.configMap.values())
        with open(self.newPath, 'w') as file:
            for item in values:
                self.write2(file, item, 0)
                file.write("\n")

    def write2(self, file: TextIO, config: Config, leftInterval: int) -> None:
        val = self.parseValue(config.value, leftInterval)
        line = "%s:%s\n" % (self.TAB * leftInterval + config.key, val)
        file.write(line)
        for item in config.children:
            self.write2(file, item, leftInterval + 1)

    def analyze(self, line: str) -> None:
        if line.startswith('#'):
            return
        configMap = line.split("=")
        if len(configMap) != 2:
            return
        configKeys = configMap[0].strip()
        configValue = configMap[1].strip()
        keyList = configKeys.split(".")
        key = keyList[0]
        keyList = keyList[1:]
        cur_config = None
        if key not in self.configMap.keys():
            cur_config = Config()
            cur_config.key = key
            self.configMap[key] = cur_config
        else:
            cur_config = self.configMap[key]

        for item in keyList:
            k = self.parseKey(item)
            children = cur_config.children
            temp = None
            for item2 in children:
                if item2.key == k:
                    temp = item2
                    break
            if temp is None:
                temp = Config()
                temp.key = k
                children.append(temp)
            cur_config = temp

        cur_config.addValue(configValue)

    def parseValue(self, val: str, leftInterval: int) -> str:
        if val is None or len(val) <= 0:
            return ""
        if val.find(",") != -1:
            values = val.split(",")
            temp = self.TAB * leftInterval + self.ARRAY_VALUE_START_MARK
            result = "%s\n" % self.ONE_SPACE
            for item in values:
                result += temp + item + "\n"
            return result
        else:
            return self.ONE_SPACE + val

    def parseKey(self, key: str) -> str:
        rIndex = key.rfind('[')
        if rIndex != -1:
            return key[0: rIndex]
        else:
            return key


if __name__ == '__main__':
    path = "/Users/liangyuanliu/Desktop/projects/lm_demo/src/main/java/funtools/python/data/application.properties"
    ConvertProperties2Yaml(path).convert()
